<script setup>
import { ref, defineAsyncComponent } from 'vue'
import CodeBlock from '@components/CodeBlock.vue'

// 编译器宏演示组件 - 作为动态组件加载
const CompilerOptionsDemo = defineAsyncComponent(() => import('./CompilerOptions.vue'))
const CompilerSlotsDemo = defineAsyncComponent(() => import('./CompilerSlots.vue'))
const CompilerModelDemo = defineAsyncComponent(() => import('./CompilerModel.vue'))
const CompilerExposeDemo = defineAsyncComponent(() => import('./CompilerExpose.vue'))

// 当前激活的标签
const activeTab = ref('options')

// 代码示例 - 使用对象存储简单的代码描述
const codeDescriptions = {
  options: {
    title: 'defineOptions 宏',
    description: '允许在 script setup 中直接定义组件选项',
    features: ['name', 'inheritAttrs', 'components'],
    language: 'javascript'
  },
  slots: {
    title: 'defineSlots 宏',
    description: '用于类型安全地声明组件的插槽',
    features: ['默认插槽', '具名插槽', '类型参数'],
    language: 'typescript'
  },
  model: {
    title: 'defineModel 宏',
    description: '简化v-model双向绑定',
    features: ['基本用法', '自定义选项', 'getter/setter'],
    language: 'javascript'
  },
  expose: {
    title: 'defineExpose 宏',
    description: '暴露组件的公共方法和属性给父组件',
    features: ['响应式数据', '方法', '重置功能'],
    language: 'javascript'
  },
  propsEmits: {
    title: 'defineProps/defineEmits 宏',
    description: '类型化的Props和Emits定义',
    features: ['泛型类型', '可选属性', '事件类型'],
    language: 'typescript'
  }
}

// 最佳实践提示
const bestPractices = [
  { title: '使用TypeScript配合', content: '编译器宏在TypeScript项目中效果最佳，可以获得完整的类型支持和IDE提示' },
  { title: '按需使用', content: '只在需要时使用这些宏，避免不必要的复杂性' },
  { title: 'defineModel简化v-model', content: '优先使用defineModel代替传统的props+emit模式处理双向绑定' },
  { title: '类型安全的插槽', content: '使用defineSlots为插槽提供类型定义，提高组件的可维护性' },
  { title: '明确的组件边界', content: '使用defineExpose明确声明组件的公共接口，避免依赖内部实现' }
]
</script>

<template>
  <div class="compiler-macros-demo">
    <h1 class="demo-title">Vue 3 编译器宏演示</h1>
    
    <!-- 功能介绍 -->
    <div class="intro-section">
      <p>Vue 3 提供了一系列编译器宏，用于增强 <code>script setup</code> 的能力，使组件开发更加类型安全和便捷。</p>
      <p>这些宏包括 defineOptions、defineSlots、defineModel、defineExpose 等，本演示展示它们的使用方法和最佳实践。</p>
    </div>

    <!-- 标签页导航 -->
    <div class="tabs">
      <button 
        v-for="tab in ['options', 'slots', 'model', 'expose', 'props-emits']" 
        :key="tab"
        class="tab-button"
        :class="{ active: activeTab === tab }"
        @click="activeTab = tab"
      >
        {{ 
          tab === 'options' ? 'defineOptions' :
          tab === 'slots' ? 'defineSlots' :
          tab === 'model' ? 'defineModel' :
          tab === 'expose' ? 'defineExpose' :
          'defineProps/Emits' 
        }}
      </button>
    </div>

    <!-- 演示内容区域 -->
    <div class="demo-content">
      <!-- defineOptions 演示 -->
      <div v-if="activeTab === 'options'" class="demo-section">
        <h2>1. defineOptions - 组件选项定义</h2>
        
        <div class="demo-card">
          <p>defineOptions 宏允许在 script setup 中直接定义组件选项，如 name、inheritAttrs 等。</p>
          
          <div class="demo-preview">
            <CompilerOptionsDemo />
          </div>
        </div>
        
        <div class="code-section">
          <h3>{{ codeDescriptions.options.title }}</h3>
          <p>{{ codeDescriptions.options.description }}</p>
          <ul>
            <li v-for="feature in codeDescriptions.options.features" :key="feature">• {{ feature }}</li>
          </ul>
        </div>
      </div>

      <!-- defineSlots 演示 -->
      <div v-if="activeTab === 'slots'" class="demo-section">
        <h2>2. defineSlots - 类型安全的插槽定义</h2>
        
        <div class="demo-card">
          <p>defineSlots 宏用于在 TypeScript 中为组件的插槽提供类型定义，实现类型安全的插槽使用。</p>
          
          <div class="demo-preview">
            <CompilerSlotsDemo>
              <template #header>
                <h3>这是自定义标题</h3>
              </template>
              
              <template #default="{ user }">
                <div class="user-info">
                  <p><strong>姓名:</strong> {{ user.name }}</p>
                  <p><strong>年龄:</strong> {{ user.age }}</p>
                </div>
              </template>
              
              <template #footer="{ message }">
                <p class="footer-message">{{ message }}</p>
              </template>
            </CompilerSlotsDemo>
          </div>
        </div>
        
        <div class="code-section">
          <h3>{{ codeDescriptions.slots.title }}</h3>
          <p>{{ codeDescriptions.slots.description }}</p>
          <ul>
            <li v-for="feature in codeDescriptions.slots.features" :key="feature">• {{ feature }}</li>
          </ul>
        </div>
      </div>

      <!-- defineModel 演示 -->
      <div v-if="activeTab === 'model'" class="demo-section">
        <h2>3. defineModel - 简化的双向绑定</h2>
        
        <div class="demo-card">
          <p>defineModel 宏简化了组件的双向绑定实现，不再需要手动定义 props 和 emit。</p>
          
          <div class="demo-preview">
            <CompilerModelDemo />
          </div>
        </div>
        
        <div class="code-section">
          <h3>{{ codeDescriptions.model.title }}</h3>
          <p>{{ codeDescriptions.model.description }}</p>
          <ul>
            <li v-for="feature in codeDescriptions.model.features" :key="feature">• {{ feature }}</li>
          </ul>
        </div>
      </div>

      <!-- defineExpose 演示 -->
      <div v-if="activeTab === 'expose'" class="demo-section">
        <h2>4. defineExpose - 组件公共接口</h2>
        
        <div class="demo-card">
          <p>defineExpose 宏用于显式声明组件向父组件暴露的属性和方法，增强组件的封装性。</p>
          
          <div class="demo-preview">
            <CompilerExposeDemo />
          </div>
        </div>
        
        <div class="code-section">
          <h3>{{ codeDescriptions.expose.title }}</h3>
          <p>{{ codeDescriptions.expose.description }}</p>
          <ul>
            <li v-for="feature in codeDescriptions.expose.features" :key="feature">• {{ feature }}</li>
          </ul>
        </div>
      </div>

      <!-- defineProps/Emits 演示 -->
      <div v-if="activeTab === 'props-emits'" class="demo-section">
        <h2>5. defineProps/defineEmits - 类型化的组件通信</h2>
        
        <div class="demo-card">
          <p>在 TypeScript 中，defineProps 和 defineEmits 可以使用泛型来提供完整的类型支持。</p>
        </div>
        
        <div class="code-section">
          <h3>{{ codeDescriptions.propsEmits.title }}</h3>
          <p>{{ codeDescriptions.propsEmits.description }}</p>
          <ul>
            <li v-for="feature in codeDescriptions.propsEmits.features" :key="feature">• {{ feature }}</li>
          </ul>
        </div>
      </div>
    </div>

    <!-- 最佳实践 -->
    <div class="demo-section">
      <h2>6. 最佳实践</h2>
      
      <div class="practices-grid">
        <div class="practice-card" v-for="practice in bestPractices" :key="practice.title">
          <h3>{{ practice.title }}</h3>
          <p>{{ practice.content }}</p>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.compiler-macros-demo {
  max-width: 1200px;
  margin: 0 auto;
  padding: 2rem;
}

.demo-title {
  color: #333;
  margin-bottom: 1.5rem;
  text-align: center;
}

.intro-section {
  background-color: #f8f9fa;
  padding: 1.5rem;
  border-radius: 8px;
  margin-bottom: 2rem;
  text-align: center;
  line-height: 1.6;
}

.intro-section code {
  background-color: #e9ecef;
  padding: 0.2rem 0.4rem;
  border-radius: 4px;
  font-family: 'Monaco', 'Menlo', monospace;
}

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 2rem;
  background-color: #f8f9fa;
  padding: 0.5rem;
  border-radius: 8px;
}

.tab-button {
  padding: 0.75rem 1.5rem;
  border: none;
  background-color: transparent;
  color: #666;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s;
  font-size: 0.9rem;
  font-weight: 500;
}

.tab-button:hover {
  background-color: #e9ecef;
  color: #333;
}

.tab-button.active {
  background-color: #42b883;
  color: white;
}

.demo-content {
  margin-bottom: 3rem;
}

.demo-section {
  margin-bottom: 3rem;
}

.demo-section h2 {
  color: #42b883;
  margin-bottom: 1.5rem;
  border-bottom: 2px solid #42b883;
  padding-bottom: 0.5rem;
}

.demo-section h3 {
  color: #333;
  margin-bottom: 1rem;
}

.demo-card {
  background-color: white;
  border-radius: 12px;
  padding: 1.5rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  margin-bottom: 1.5rem;
  transition: all 0.2s ease;
  border: 1px solid rgba(255, 255, 255, 0.2);
}

/* 深色模式下的液态玻璃效果 */
@media (prefers-color-scheme: dark) {
  .demo-card {
    background: rgba(28, 28, 30, 0.8);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
  }
}

.demo-preview {
  margin-top: 1rem;
  padding: 1rem;
  background-color: #f8f9fa;
  border-radius: 6px;
  border: 1px solid #e9ecef;
}

.user-info {
  background-color: #e3f2fd;
  padding: 1rem;
  border-radius: 6px;
  margin: 1rem 0;
}

.footer-message {
  background-color: #fff3e0;
  padding: 0.75rem;
  border-radius: 6px;
  text-align: center;
  font-style: italic;
}

.code-section {
  background-color: white;
  border-radius: 8px;
  padding: 1.5rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.practices-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 1.5rem;
}

.practice-card {
  background-color: white;
  border-radius: 8px;
  padding: 1.5rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  border-left: 4px solid #42b883;
}

.practice-card h3 {
  color: #42b883;
  margin-bottom: 0.5rem;
}

/* 响应式布局 */
@media (max-width: 768px) {
  .compiler-macros-demo {
    padding: 1rem;
  }
  
  .tabs {
    flex-direction: column;
  }
  
  .tab-button {
    width: 100%;
    text-align: left;
  }
}
</style>